package com.haixee.parkdemo.auth.jwt.alg;

import cn.hutool.crypto.SecureUtil;
import com.haixee.parkdemo.auth.enums.AuthScope;
import com.haixee.parkdemo.auth.jwt.JwsToken;
import com.haixee.parkdemo.auth.jwt.JwsTokenExtra;
import com.haixee.parkdemo.auth.jwt.JwtOperator;
import com.haixee.parkdemo.auth.properties.WebProperties;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.Date;

/**
 * @author RUIFENG GUO
 * 2020/3/25 22:36
 */
@Slf4j
public class ECDSAJwt implements JwtOperator {

    private static final SignatureAlgorithm ALGORITHM = SignatureAlgorithm.ES256;

    private final PrivateKey privateKey;

    private final PublicKey publicKey;

    private long expire = 60 * 60 * 24 * 1000 * 20;

    private final String name;

    public ECDSAJwt() {
        KeyPair keyPair = Keys.keyPairFor(ALGORITHM);
        privateKey = keyPair.getPrivate();
        publicKey = keyPair.getPublic();
        name = "";
    }

    public ECDSAJwt(String name, WebProperties.Jwt jwt) {

        privateKey = SecureUtil.generatePrivateKey(ALGORITHM.getFamilyName(), Base64.getDecoder().decode(jwt.getPrikey().getBytes()));
        publicKey = SecureUtil.generatePublicKey(ALGORITHM.getFamilyName(), Base64.getDecoder().decode(jwt.getPubkey().getBytes()));
//        privateKey = new ECPrivateKeyImpl(Base64.getDecoder().decode(jwt.getPrikey()));
//        publicKey = new ECPublicKeyImpl(Base64.getDecoder().decode(jwt.getPubkey()));
        Long newExpire = jwt.getExpire();
        if (newExpire != null) {
            expire = newExpire * 1000;
        }

        this.name = name;
    }

    @Override
    public String generateJwt(Integer uid) {

        long expireTime = System.currentTimeMillis() + expire;

        return Jwts.builder()
                .signWith(privateKey, ALGORITHM)
                .claim("uid", uid)
                .setExpiration(new Date(expireTime))
                .compact();
    }

    @Override
    public String generateJwtWithExtra(Integer uid, AuthScope scope, JwsTokenExtra extra) {
        long expireTime = System.currentTimeMillis() + expire;

        return Jwts.builder()
                .signWith(privateKey, ALGORITHM)
                .claim("uid", uid)
                .claim("extra", extra)
                .claim("scope", scope.getCode())
                .setExpiration(new Date(expireTime))
                .compact();
    }

    @Override
    public JwsToken getToken(String token) {
        return getJwsToken(token, publicKey);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public long getExpire() {
        return expire;
    }

    public static void main(String[] args) {
        KeyPair keyPair = Keys.keyPairFor(ALGORITHM);
        System.out.println(Encoders.BASE64.encode(keyPair.getPrivate().getEncoded()));
        System.out.println(Encoders.BASE64.encode(keyPair.getPublic().getEncoded()));
    }
}
